﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Resources;
using System.Net;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using System.Globalization;
using System.Threading;

namespace raktajino
{
    public partial class UpdateDialog : Form
    {
        #region Globals
        WebClient wc = null;
        string fileName = string.Empty;
        System.Windows.Forms.Timer timer_StartAutoUpdate = null;
        int startAutoUpdateCountdown;
        bool isUpdating = false;
        public string HostingOptionsURL { get; set; }
        public string InstallationRequirementsURL { get; set; }
        public string Culture { get; set; }
        public string VersionCheckInterval { get; set; }
        public string UpdateURL { get; set; }
        #endregion


        public UpdateDialog()
        {
            InitializeComponent();
            this.SuspendLayout();
         }

        private void UpdateDialog_Load(object sender, EventArgs e)
        {
            //localize strings.
            if (!string.IsNullOrEmpty(Culture))
            {
                CultureInfo ci = new CultureInfo(Culture);
                Thread.CurrentThread.CurrentUICulture = ci;
                Application.CurrentCulture = ci;
            }
            ResourceManager LocRM = new ResourceManager("raktajino.WinformStrings", typeof(RAKTAJINO).Assembly);
            this.label_updatetitle.Text = LocRM.GetString("label_updatetitle");
            this.label_updateinfo.Text = LocRM.GetString("label_updateinfo");
            this.button_cancel.Text = LocRM.GetString("button_cancel");
            this.button_update.Text = LocRM.GetString("button_update");
            this.label_autoupdateinfo.Text = LocRM.GetString("label_autoupdateinfo");
            this.label_updatestatus.Text = string.Format("{0}: {1}  ->  {2}: {3} ", LocRM.GetString("label_updatestatusServerVersion"),UpdateConfig.Instance.ServerVersion, LocRM.GetString("label_updatestatusYourVersion"),Assembly.GetExecutingAssembly().GetName().Version.ToString());
            this.Text = LocRM.GetString("UpdateDialog");
            this.ResumeLayout();

            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            wc = new WebClient();
            wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
            wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
            //set autoupdate countdown from config
            if (!int.TryParse(UpdateConfig.Instance.AutoUpdateCountdown, out startAutoUpdateCountdown))
            {   
                startAutoUpdateCountdown = 300; //defaults to 5 mins if parsing error occurs.
            }
            timer_StartAutoUpdate = new System.Windows.Forms.Timer();
            timer_StartAutoUpdate.Interval = startAutoUpdateCountdown * 1000; //in milliseconds
            timer_StartAutoUpdate.Enabled = true;
            timer_StartAutoUpdate.Tick += new EventHandler(timer_StartAutoUpdate_Tick);
            timer_autoupdateinfo.Enabled = true;
        }

        #region BackgroundWorker
        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            isUpdating = true;
            Uri uri = new Uri(UpdateConfig.Instance.DownloadUrl);
            string file = Path.GetFileName(uri.GetComponents(UriComponents.Path, UriFormat.SafeUnescaped));
            string downloadpath = System.Windows.Forms.Application.LocalUserAppDataPath + "\\downloads";
            fileName = Path.Combine(downloadpath, file);
            if (!Directory.Exists(downloadpath))
            {
                Directory.CreateDirectory(downloadpath);
            }

            wc.DownloadFileAsync(uri, fileName);
            while (isUpdating)
            {
                System.Threading.Thread.Sleep(500);
            }
        }

        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label_updatetitle.Text = string.Format("Downloading: {0}%", e.ProgressPercentage);
            progressBar1.Value = e.ProgressPercentage;
        }

        void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            label_updatetitle.Text = string.Format("Upgrading");
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        #endregion

        #region WebClient
        void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            backgroundWorker1.ReportProgress(e.ProgressPercentage);
        }

        void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ResourceManager LocRM = new ResourceManager("raktajino.WinformStrings", typeof(RAKTAJINO).Assembly);
            if (e.Cancelled == true || e.Error != null)
            {
                switch (e.Cancelled)
                {
                    case true:
                        this.DialogResult = DialogResult.Cancel;
                        break;
                    case false:
                        this.DialogResult = DialogResult.Abort;
                        MessageBox.Show(string.Format("{0}\n{1}: {2}", LocRM.GetString("errorDuringUpdate"), LocRM.GetString("Error"), e.Error.Message), LocRM.GetString("Error"));
                        break;
                }
                isUpdating = false;
                return;
            }

            if (!File.Exists(fileName))
            {
                this.DialogResult = DialogResult.Abort;
                MessageBox.Show(string.Format("{0}\n{1}: {2}", LocRM.GetString("errorDuringUpdate"), LocRM.GetString("Error"), LocRM.GetString("A_download_error_has_occurred")), LocRM.GetString("Error"));
                return;
            }
            Process proc = new Process();
            string batchPath = System.Windows.Forms.Application.LocalUserAppDataPath + "\\downloads";
            string batchfile = Path.Combine(batchPath, "update.cmd");
            StreamWriter writer = new StreamWriter(batchfile);
            writer.WriteLine(string.Format("start /wait msiexec.exe /Package \"{0}\" {1} HOSTINGOPTIONSURL=\"{2}\" INSTALLATIONREQUIREMENTSURL=\"{3}\" CULTURE={4} UPDATEURL=\"{5}\" VERSIONCHECKINTERVAL={6}", fileName, UpdateConfig.Instance.UpdateCommand, HostingOptionsURL, InstallationRequirementsURL, Culture, UpdateURL, VersionCheckInterval));
            string appPath = Path.GetDirectoryName(Application.ExecutablePath);
            writer.WriteLine(string.Format("cd \"{0}\"",appPath));
            string appName = Path.GetFileName(Application.ExecutablePath);
            writer.WriteLine(string.Format("start {0}", appName));
            writer.WriteLine("exit");
            writer.Close();

            ProcessStartInfo psi = new ProcessStartInfo(batchfile, "");
            psi.UseShellExecute = true;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            proc.StartInfo = psi;
            proc.Start();
            isUpdating = false;
        }
        #endregion

        #region Timers
        void timer_StartAutoUpdate_Tick(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy && !wc.IsBusy)
            {
                label_updatetitle.Text = string.Format("Downloading: {0}%", 0);
                this.UseWaitCursor = true;
                backgroundWorker1.RunWorkerAsync();
            }
            timer_StartAutoUpdate.Enabled = false;
            timer_autoupdateinfo.Enabled = false;
            label_autoupdateinfo.Text = string.Empty;
        }

        private void timer_autoupdateinfo_Tick(object sender, EventArgs e)
        {
            startAutoUpdateCountdown--;
            label_autoupdateinfo.Text = string.Format("Auto update in {0} seconds.", startAutoUpdateCountdown);

        }
        #endregion

        #region Buttons
        private void button_update_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy && !wc.IsBusy)
            {
                timer_autoupdateinfo.Enabled = false;
                label_updatetitle.Text = string.Format("Downloading: {0}%", 0);
                this.UseWaitCursor = true;
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void button_cancel_Click(object sender, EventArgs e)
        {
            if (wc.IsBusy)
            {
                wc.CancelAsync();
                this.Close();
            }

            this.Close();
        }
        #endregion

    }
}
